Service.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. "use client";
  2. import { ServiceTypes } from "@/api/customservice";
  3. import { getPaysApi, lredPacketApi, PayDataType, redPacketApi } from "@/api/promo";
  4. import UserRecharge, { ModalRefProps, Timeout } from "@/components/ModalPopup/RechargeModal";
  5. import RedPacketModal, { RedPacketModalProps } from "@/components/ModalPopup/RedPacketModal";
  6. import SlotsModal, { SlotModalRefProps } from "@/components/ModalPopup/SlotsModal";
  7. import WheelModal, { WheelModalProps } from "@/components/ModalPopup/WheelModal";
  8. import { getWheelApi } from "@/api/cashWheel";
  9. import { getShareApi } from "@/api/config";
  10. import { getGiveInfoApi } from "@/api/slots";
  11. import { Link } from "@/i18n/routing";
  12. import { useGlobalNoticeStore } from "@/stores/useGlobalNoticeStore";
  13. import useWheelStore from "@/stores/useWheelStore";
  14. import { getToken } from "@/utils/Cookies";
  15. import { useRequest } from "ahooks";
  16. import { Badge } from "antd-mobile";
  17. import { useTranslations } from "next-intl";
  18. import Image from "next/image";
  19. import { useSearchParams } from "next/navigation";
  20. import { FC, useEffect, useRef } from "react";
  21. interface Props {
  22. services: ServiceTypes[];
  23. }
  24. /**
  25. * 免费送活动
  26. */
  27. const SlotSection = () => {
  28. const slotsRef = useRef<SlotModalRefProps | null>(null);
  29. const getSlots = async () => {
  30. const token = getToken();
  31. if (token) {
  32. const result = await getGiveInfoApi();
  33. return result.data;
  34. } else {
  35. return Promise.resolve({});
  36. }
  37. };
  38. const { data: slots, run: slotRun } = useRequest<any, any>(getSlots, {
  39. pollingInterval: 2000,
  40. pollingErrorRetryCount: 1,
  41. pollingWhenHidden: false,
  42. });
  43. const slotHandler = () => {
  44. slotsRef.current?.onOpen(slots);
  45. };
  46. return (
  47. <>
  48. {slots?.id ? (
  49. <img
  50. src={"/slots/slots-icon.gif"}
  51. className={"mb-[0.2778rem] w-[100%]"}
  52. onClick={slotHandler}
  53. />
  54. ) : null}
  55. {/*随机送*/}
  56. <SlotsModal ref={slotsRef} onAfterHandler={slotRun} />
  57. </>
  58. );
  59. };
  60. /**
  61. * 轮盘
  62. */
  63. const WheelSection = () => {
  64. const wheelModalRef = useRef<WheelModalProps | null>(null);
  65. const { wheelStatus, wheelCurrent, setWheel } = useWheelStore((state) => ({
  66. wheelStatus: state.status,
  67. wheelCurrent: state.currentWheel,
  68. setWheel: state.setWheel,
  69. }));
  70. useEffect(() => {
  71. setWheel().then((data) => {
  72. if (data && useWheelStore.getState().status === 1) {
  73. wheelModalRef.current?.onOpen(data);
  74. }
  75. });
  76. }, []);
  77. return (
  78. <>
  79. {wheelStatus === 2 ? (
  80. <Link
  81. href={"/cashWheel"}
  82. className={
  83. "mb-[0.2778rem] flex h-[0.54rem] w-[0.54rem] items-center" +
  84. " justify-center rounded-[50%] bg-gradient-to-b from-[#0575e6] to-[#00f260]"
  85. }
  86. >
  87. <Image src={"/wheels/wheel-icon.gif"} alt={"wheel"} width={100} height={100} />
  88. </Link>
  89. ) : null}
  90. {/* 轮盘弹窗 */}
  91. <WheelModal ref={wheelModalRef} />
  92. </>
  93. );
  94. };
  95. /**
  96. * 首充
  97. */
  98. const PaySection = () => {
  99. const token = getToken();
  100. const userRechargeRef = useRef<ModalRefProps>(null);
  101. // 首充活动
  102. const getPayInfo = async (): Promise<PayDataType> => {
  103. if (token) {
  104. const result = await getPaysApi();
  105. return result.data;
  106. } else {
  107. return Promise.resolve({
  108. first_pay: [],
  109. pay: [],
  110. });
  111. }
  112. };
  113. const { data: paysInfo, run: payRun } = useRequest<PayDataType, any>(getPayInfo, {
  114. pollingErrorRetryCount: 1,
  115. pollingWhenHidden: false,
  116. });
  117. return (
  118. <>
  119. {paysInfo &&
  120. paysInfo.first_pay &&
  121. paysInfo.first_pay.map((item, index) => {
  122. return (
  123. <div
  124. key={index}
  125. className={`mb-[0.2778rem] flex cursor-pointer flex-col items-center`}
  126. >
  127. <img
  128. className={"w-[0.54rem]"}
  129. src="/hby/recharge.png"
  130. onClick={() => {
  131. userRechargeRef.current?.onOpen &&
  132. userRechargeRef.current?.onOpen(paysInfo?.first_pay, index);
  133. }}
  134. />
  135. {item.end_time > 0 ? (
  136. <Timeout
  137. className={
  138. "relative before:left-0 before:top-0 before:content-['']" +
  139. " -m-[0.0417rem] before:h-[100%] before:blur-[0.0486rem]" +
  140. " before:absolute before:-z-10 before:w-[100%] before:bg-[#ed9d00]" +
  141. " text-[0.08rem]" +
  142. " z-1 text-[#fff]"
  143. }
  144. endTime={item.end_time}
  145. onEndHandler={payRun}
  146. />
  147. ) : null}
  148. </div>
  149. );
  150. })}
  151. {/*首充弹窗*/}
  152. <UserRecharge ref={userRechargeRef} />
  153. </>
  154. );
  155. };
  156. /**
  157. * 红包雨
  158. */
  159. const RedPacketSection = () => {
  160. const token = getToken();
  161. const redPacketModalRef = useRef<RedPacketModalProps>(null);
  162. const getRedPacketInfo = async () => {
  163. try {
  164. let redPacketInfo: any;
  165. let actList: any = [];
  166. if (token) {
  167. redPacketInfo = await lredPacketApi();
  168. actList = redPacketInfo.data?.red_packets || [];
  169. } else {
  170. redPacketInfo = await redPacketApi();
  171. actList = redPacketInfo.data || [];
  172. }
  173. // 已经开始
  174. return actList.filter((aItem: any) => {
  175. return aItem.is_start;
  176. });
  177. } catch (error) {}
  178. };
  179. // 红包雨轮询
  180. const { data: packets, run } = useRequest<any[], any>(getRedPacketInfo, {
  181. pollingInterval: 5000,
  182. pollingErrorRetryCount: 1,
  183. pollingWhenHidden: false,
  184. });
  185. return (
  186. <>
  187. {packets?.map((item, index) => {
  188. const icons = JSON.parse(item.icon);
  189. const icon = icons[icons.length - 1];
  190. return (
  191. <div key={index} className={`mb-[0.2778rem] cursor-pointer`}>
  192. <img
  193. className={"w-[0.54rem] object-fill"}
  194. src={icon}
  195. onClick={() => {
  196. redPacketModalRef.current?.onOpen(packets, index);
  197. }}
  198. />
  199. </div>
  200. );
  201. })}
  202. {/*红包雨弹窗*/}
  203. <RedPacketModal ref={redPacketModalRef} onAfterHandler={run} />
  204. </>
  205. );
  206. };
  207. const MessageSection = () => {
  208. const { unread, userUnred } = useGlobalNoticeStore((state) => ({
  209. unread: state.unread,
  210. userUnred: state.userUnred,
  211. }));
  212. return (
  213. <>
  214. {unread || userUnred ? (
  215. <Link
  216. href={"/notification"}
  217. className={
  218. "mb-[0.2778rem] flex h-[0.54rem] w-[0.54rem] items-center" +
  219. " justify-center rounded-[50%] bg-gradient-to-t from-[#ffa111]" +
  220. " to-[#ffcf35]"
  221. }
  222. >
  223. <Badge content={userUnred + unread} style={{ "--top": "12px" }}>
  224. <i className={"iconfont icon-duanxinguanli text-[0.3rem] text-[#fff]"}></i>
  225. </Badge>
  226. </Link>
  227. ) : null}
  228. </>
  229. );
  230. };
  231. /**
  232. * 客服
  233. */
  234. const CustomerSection: FC<Omit<Props, "socials">> = (props) => {
  235. const { services } = props;
  236. const defaultService = services?.filter((item) => item.is_suspend === 1);
  237. return (
  238. <>
  239. {defaultService?.map((item, index) => (
  240. <Link
  241. key={index}
  242. href={item.url}
  243. className={
  244. "flex h-[0.54rem] w-[0.54rem] items-center justify-center rounded-[50%]" +
  245. " bg-gradient-to-t from-[#ff611b] to-[#ffcf35]"
  246. }
  247. target={"_blank"}
  248. >
  249. <img
  250. className={"h-[0.3889rem] w-[0.3889rem] object-contain"}
  251. src={item.icon_url}
  252. alt={""}
  253. ></img>
  254. </Link>
  255. ))}
  256. </>
  257. );
  258. };
  259. const ServiceWidget: FC<Props> = (props) => {
  260. const { services } = props;
  261. const newServices = services?.filter((item) => item.status === 1) || [];
  262. const getWheel = () => {
  263. if (!getToken()) return Promise.resolve(undefined);
  264. return getWheelApi().then((res) => {
  265. return res.data;
  266. });
  267. };
  268. const serach = useSearchParams();
  269. useEffect(() => {
  270. // 数据存储,侧边栏使用
  271. // setSocials(socials);
  272. // 分享地址
  273. if (serach.get("ch")) {
  274. getShareApi({ channel_url: window.location.href });
  275. }
  276. }, []);
  277. const t = useTranslations("HomePage");
  278. return (
  279. <>
  280. <div
  281. className={`absolute bottom-[0.84rem] right-[0.12rem] z-50 flex w-[0.6944rem] flex-col items-center justify-center`}
  282. >
  283. <SlotSection />
  284. {/*轮盘 */}
  285. <WheelSection />
  286. {/*首充*/}
  287. <PaySection />
  288. {/* 红包雨icon */}
  289. <RedPacketSection />
  290. {/*未读消息*/}
  291. <MessageSection />
  292. {/*客服*/}
  293. <CustomerSection services={services} />
  294. </div>
  295. <div
  296. className={`grid`}
  297. style={{
  298. gridTemplateColumns: ` repeat(${newServices && newServices.length >= 5 ? 5 : (newServices?.length ?? 1)},1fr)`,
  299. }}
  300. >
  301. {newServices.map((service, index) => {
  302. return (
  303. <Link
  304. key={index}
  305. href={service.url}
  306. target={"_blank"}
  307. className="bg-white m-[0.05rem] h-[0.3889rem] w-[0.3889rem] rounded"
  308. >
  309. <img
  310. className={"h-[0.3889rem] w-[0.3889rem]"}
  311. src={service.icon_url}
  312. ></img>
  313. </Link>
  314. );
  315. })}
  316. </div>
  317. <div className={"text-[#ff6a01]"}>{t("Service")}</div>
  318. {/*share*/}
  319. <div className={"my-[0.2rem] text-[0.12rem] text-[#adadad]"}>{t("Share")}</div>
  320. <Image
  321. src={"/logo.png"}
  322. alt={"BCWIN777"}
  323. width={120}
  324. height={180}
  325. className={"mb-[0.2rem]"}
  326. />
  327. </>
  328. );
  329. };
  330. export default ServiceWidget;